#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include <sys/wait.h>

#include "Socket.hpp"
#include "InetAddr.hpp"

using namespace SocketModule;
using namespace LogModule;

using tcphandler_t = std::function<bool(SockPtr, InetAddr)>;

namespace TcpServerModule
{
    class TcpServer
    {
    public:
        TcpServer(int port)
            : _listensockp(std::make_unique<TcpSocket>())
            , _isrunning(false)
            , _port(port)
        {}

        ~TcpServer()
        {
            _listensockp->Close();
        }

        void InitServer(tcphandler_t handler)
        {
            _listensockp->BuildTcpSocketMethod(_port);
            _handler = handler;
        }

        void Loop()
        {
            _isrunning = true;
            while (_isrunning)
            {
                // 1. 获取连接: 获取网络通信sockfd && 客户端的
                InetAddr clientaddr;
                auto sockfd = _listensockp->AcceptOrDie(&clientaddr);
                if (sockfd == nullptr)
                    continue;
                LOG(LogLevel::DEBUG) << "get a new client info is: " << clientaddr.Addr();

                // 2. IO处理
                pid_t id = fork();
                if (id == 0)
                {
                    // 子进程关闭listensockfd
                    _listensockp->Close();
                    if (fork() > 0)
                        exit(0); // 子进程直接退出

                    // 孙子进程进行IO处理
                    _handler(sockfd, clientaddr);
                    exit(0);
                }
                // 父进程关闭sockfd
                sockfd->Close();
                waitpid(id, nullptr, 0); // 子进程直接退出, 父进程无需阻塞等待
            }
            _isrunning = false;
        }

    private:
        std::unique_ptr<Socket> _listensockp;
        bool _isrunning;
        tcphandler_t _handler;
        int _port;
    };
}